package com.tbfeng.id.builder.service.impl;

import com.tbfeng.id.builder.domian.Segment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.PreparedStatement;

/**
 * @author linjf48556
 * @Description
 * @date 2024-03-12
 **/
@Slf4j
@Component
public class PubSeqService {

    @Resource
    private JdbcTemplate jdbcTemplate;

    String QUERY_SQL = "select seq_field_name as biz_tag,seq_current_value as max_id,100 as step from dbtrade.pub_pubseq where seq_field_name=?";
    String UPDATE_SQL = "update dbtrade.pub_pubseq set seq_current_value=? where seq_field_name=? and seq_current_value=?";
    String INSERT_SQL = "insert into dbtrade.pub_pubseq (seq_field_name,seq_name,seq_current_value,seq_max_value,seq_reset_everyday,seq_start_value,seq_cycle) values (?, ?, 0, 99999999, 0, 1, 0)";

    public Segment getSegment(String bizTag) {
        Segment currentSegment = querySegment(bizTag);
        // 查不到创建
        if (currentSegment == null || currentSegment.getMaxId() == null) {
            // 在2.0的pub_pubseq创建一条序号数据
            insertSegment(bizTag);
            currentSegment = new Segment(bizTag, 100, 0L);
        }
        Long oldMaxId = currentSegment.getMaxId();
        Long newMaxId = currentSegment.getMaxId() + currentSegment.getStep();
        // oldMaxId 乐观锁
        int row = jdbcTemplate.update(UPDATE_SQL, newMaxId, bizTag, oldMaxId);
        if (row != 1) {
            throw new RuntimeException("更新数据库 Segment 表失败");
        }
        return currentSegment;
    }

    public Segment querySegment(String bizTag) {
        Segment segment = new Segment();
        jdbcTemplate.query(QUERY_SQL, rs -> {
            segment.setStep(rs.getInt("step"));
            segment.setMaxId(rs.getLong("max_id"));
            segment.setBizTag(rs.getString("biz_tag"));
        }, bizTag);

        return segment;
    }

    public void insertSegment(String bizTag) {
        jdbcTemplate.execute((PreparedStatementCreator) con -> {
            PreparedStatement preparedStatement = con.prepareStatement(INSERT_SQL);
            preparedStatement.setString(1, bizTag);
            preparedStatement.setString(2, bizTag);
            return preparedStatement;
        }, ps -> {
            ps.executeUpdate();
            int updateCount = ps.getUpdateCount();
            log.info("是否新增序列号[{}]成功：{}", bizTag, updateCount == 1);
            return updateCount;
        });
    }

}
